#ifndef CLOUDPROCESSWIDGET_H
#define CLOUDPROCESSWIDGET_H

#include <QWidget>
#include <QThread>

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)


#include <vector>
#include <pcl/common/common.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/filter.h>
#include <pcl/io/pcd_io.h>
#include <vtkPlaneSource.h>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <pcl/common/transforms.h>
#include <pcl/keypoints/uniform_sampling.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/filters/project_inliers.h>
#include <pcl/features/normal_3d_omp.h> //使用OMP需要添加的头文件
#include <algorithm>
#include <limits>
#include <fstream>
#include <pcl/features/moment_of_inertia_estimation.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/surface/organized_fast_mesh.h>
#include <pcl/surface/concave_hull.h>
#include <pcl/surface/poisson.h>
#include <pcl/io/ply/ply_parser.h>
#include <pcl/io/ply_io.h>
#include <vtkRenderWindow.h>					//vtk可视化窗口

#include <QFileDialog>
#include <iostream>
#include <QMessageBox>
#include <vtkOrientationMarkerWidget.h>
#include <QMimeDatabase>

#include <QToolBar>
#include "cloudprocessdepend.h"

typedef pcl::PointXYZ PointType;
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloudT;


struct callback_args{
    pcl::PointCloud<pcl::PointXYZ>::Ptr clicked_points;
    pcl::visualization::PCLVisualizer::Ptr viewer;
};



namespace Ui {
class CloudProcessWidget;
}

class CloudProcessWidget : public QWidget
{
    Q_OBJECT

public:
    explicit CloudProcessWidget(QWidget *parent = 0);
    ~CloudProcessWidget();

    void Init_UI();
    void Init_Signals();

    void ShowLog(QString& info);
    void ShowErrorLog(QString& info);

    void split(std::string& string_input, std::vector<std::string>&string_output, std::string& delema1);
    double getMaxValue(PointType p1, PointType p2);
    double getMinValue(PointType p1, PointType p2);

public:
    /** 显示NURBS曲线 **/
    void ShowNURBSCurve(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, double r, double g, double b, bool IFSHOWPOINT);
    void ShowNURBSCurve(pcl::PointCloud<pcl::PointXYZ> cloud, double r, double g, double b, bool IFSHOWPOINT, std::string namestr);

    /** 显示NURBS曲线上点和法线 **/
    void ShowNURBSNormals(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::Normal>::Ptr& NURBS_normals);
    void ShowNURBSNormals(pcl::PointCloud<pcl::PointXYZ> cloud, pcl::PointCloud<pcl::Normal> NURBS_normals, std::string namestr, float scale);

    /** 显示NURBS曲线点位姿 **/
    void ShowNURBSVectorDirections(pcl::PointCloud<pcl::PointXYZ> cloud, std::vector<CloudProcessDepend::Pose_Vector> NURBS_direction_vectors, std::string id, float scale);

    void ShowExtrectSlicesOutput();

    bool LoadPlyFile(std::string filename);

public slots:
    void on_action_front_triggered();	// 前视图
    void on_action_up_triggered();		// 俯视图
    void on_action_button_triggered();	// 仰视图
    void on_action_left_triggered();	// 左视图
    void on_action_right_triggered();	// 右视图
    void on_action_back_triggered();	// 后视图
    void on_actionFront_triggered();	// 前轴测
    void on_actionBack_triggered();		// 后轴测

    void on_Signal_Message(QString message);

private slots:
    void on_pushButton_addCloud_clicked();

    void on_pushButton_extractCoordinates_clicked();

    void on_pushButton_extractCoordinates_2_clicked();

    void on_pushButton_extractPose_clicked();

    void on_pushButton_saveExtractPose_clicked();

    void on_pushButton_Set_clicked();

    void on_pushButton_ReCompute_clicked();

private:
    Ui::CloudProcessWidget *ui;
    QToolBar *toolbar;

    QAction *action_front;
    QAction *action_back;
    QAction *action_left;
    QAction *action_right;
    QAction *action_up;
    QAction *action_bottom;
    QAction *action_frontIso;
    QAction *action_backIso;

    QThread* cloud_process_thread;
    CloudProcessDepend* cloudprocess;
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;				// 点云
    pcl::PolygonMesh::Ptr poly_mesh;                        // 多边形
    pcl::PointXYZ p_min, p_max;

    std::vector<pcl::PointCloud<pcl::PointXYZ>> extract_slices_NURBS;      //保存切片点云
    std::vector<pcl::PointCloud<pcl::PointXYZ>> extract_slices_points;     //保存提取点坐标
    std::vector<pcl::PointCloud<pcl::Normal>> extrace_slices_NURBS_normals;//保存提取点坐标法向量
    std::vector<std::vector<CloudProcessDepend::Pose_Vector>> extrace_slices_NURBS_direction_vectors;  //保存提取点位姿

    pcl::PointCloud<pcl::PointXYZ>::Ptr clicked_points;
    callback_args* cb_args;

    double maxLen;
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;	//可视化窗口类
};

#endif // CLOUDPROCESSWIDGET_H

